home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / jcool01.zip / M_VECTOR.C < prev    next >
C/C++ Source or Header  |  1992-09-25  |  22KB  |  570 lines

  1. //
  2. // Copyright (C) 1991 Texas Instruments Incorporated.
  3. // Copyright (C) 1992 General Electric Company.
  4. //
  5. // Permission is granted to any individual or institution to use, copy, modify,
  6. // and distribute this software, provided that this complete copyright and
  7. // permission notice is maintained, intact, in all copies and supporting
  8. // documentation.
  9. //
  10. // Texas Instruments Incorporated, General Electric Company,
  11. // provides this software "as is" without express or implied warranty.
  12. //
  13.  
  14. #include <cool/M_Vector.h>            // header of vector and its envelope
  15.  
  16. //## hack to workaround BC++ 3.1 Envelope bug
  17. #define CoolEnvelope CoolEnvelope_M_Vector
  18.  
  19. // compare_s -- Function used by == test
  20. template <class Type>
  21. Boolean (*CoolM_Vector<Type>::compare_s)(const Type&, const Type&) = &CoolM_Vector_is_data_equal;
  22.  
  23. // CoolM_Vector -- constructor specifiying size of CoolM_Vector
  24. // Input:    Length
  25. // Output:   None
  26.  
  27. template<class Type> 
  28. CoolM_Vector<Type>::CoolM_Vector(unsigned int len)
  29. : CoolBase_M_Vector(len)
  30. {
  31.   this->data = new Type[len];            // Allocate the elements
  32. }
  33.  
  34.  
  35. // CoolM_Vector -- constructor specifiying size of vector and initial value
  36. // Input:    Length and initial value
  37. // Output:   None
  38.  
  39. template<class Type> 
  40. CoolM_Vector<Type>::CoolM_Vector(unsigned int len, const Type& value)
  41. : CoolBase_M_Vector(len)
  42. {
  43.   this->data = new Type[len];            // Allocate the elements
  44.   for (int i = 0; i < len; i ++) {        // For each elmt in the CoolM_Vector
  45.     this->data[i] = value;            // Assign initial value
  46.   }
  47. }
  48.  
  49. // CoolM_Vector -- constructor specifiying size of vector and initial values
  50. // Input:    Length and initial values
  51. // Output:   None
  52. // Note: Arguments in ... can only be pointers, primitive types like int,
  53. //       and NOT OBJECTS, passed by reference or value, like vectors, matrices;
  54. //       because constructors must be known and called at compile time!!!
  55. //       Cannot have char in ..., because char is 1 instead of 4 bytes, and 
  56. //       va_arg expects sizeof(Type) a multiple of 4 bytes.
  57.  
  58. template<class Type> 
  59. CoolM_Vector<Type>::CoolM_Vector(unsigned int len, int n, Type v00, ...)
  60. : CoolBase_M_Vector(len)
  61. {
  62. #if ERROR_CHECKING
  63.   if (((sizeof(Type) % 4) != 0) ||        // Cause alignment problems
  64.       (sizeof(Type) > 8))            // User defined classes?
  65.     this->va_arg_error("Type", sizeof(Type));    // So, cannot use this constructor
  66. #endif
  67.   this->data = new Type[len];            // Allocate the elements
  68.   if (n > 0) {                    // If user specified values
  69.     va_list argp;                // Declare argument list
  70.     va_start (argp, v00);                   // Initialize macro
  71.     for (int i = 0; i < len && n; i++, n--)    // For remaining values given
  72.       if (i == 0)
  73.     this->data[0] = v00;            // Hack for v00 ...
  74.       else
  75.     this->data[i] = va_arg(argp, Type);    // Extract and assign
  76.     va_end(argp);
  77.   }
  78. }
  79.  
  80.  
  81. // CoolM_Vector -- constructor for reference to another CoolM_Vector object
  82. // Input:    CoolM_Vector reference
  83. // Output:   None
  84.  
  85. template<class Type> 
  86. CoolM_Vector<Type>::CoolM_Vector(const CoolM_Vector<Type>& v)
  87. : CoolBase_M_Vector(v)
  88. {
  89.   this->data = new Type[this->num_elmts];    // Allocate the elements
  90.   for (int i = 0; i < this->num_elmts; i ++) {    // For each element in the CoolM_Vector
  91.     this->data[i] = v.data[i];            // Copy value
  92.   }
  93. }
  94.  
  95.  
  96. // ~CoolM_Vector -- Destructor for CoolM_Vector class that frees up storage
  97. // Input:     *this
  98. // Output:    None
  99.  
  100. template<class Type> 
  101. CoolM_Vector<Type>::~CoolM_Vector() {
  102.   delete this->data;                // Free up the data space
  103. }
  104.  
  105. // fill -- Set all elements of a vector to a specified fill value
  106. // Input:  *this, reference to fill value
  107. // Output: None
  108.  
  109. template<class Type> 
  110. void CoolM_Vector<Type>::fill (const Type& value) {
  111.   for (int i = 0; i < this->num_elmts; i++)    // For each index in the CoolM_Vector
  112.       this->data[i] = value;            // Assign fill value
  113. }
  114.  
  115. // operator= -- Overload the assignment operator to assign a single 
  116. //              value to the elements of a CoolM_Vector. 
  117. // Input:       *this, reference to a value
  118. // Output:      Reference to updated CoolM_Vector object
  119.  
  120. template<class Type> 
  121. CoolM_Vector<Type>& CoolM_Vector<Type>::operator= (const Type& value) {
  122.   for (int i = 0; i < this->num_elmts; i++)    // For each index in CoolM_Vector
  123.       this->data[i] = value;            // Assign value
  124.   return *this;                    // Return CoolM_Vector reference
  125. }
  126.  
  127.  
  128. // operator= -- Overload the assignment operator to copy the elements
  129. //              in one CoolM_Vector to another. The existing storage for the 
  130. //              destination vector is freed up and new storage of the same 
  131. //              size as the source is allocated.
  132. // Input:       *this, reference to CoolM_Vector
  133. // Output:      Reference to copied CoolM_Vector object
  134.  
  135. template<class Type> 
  136. CoolM_Vector<Type>& CoolM_Vector<Type>::operator= (const CoolM_Vector<Type>& v) {
  137.   if (this != &v) {                // make sure *this != m
  138.     if (this->num_elmts != v.num_elmts) {
  139.       delete this->data;            // Free up the data space
  140.       this->num_elmts = v.num_elmts;        // Copy index specification
  141.       this->data = new Type[this->num_elmts];    // Allocate the elements
  142.     }
  143.     for (int i = 0; i < this->num_elmts; i++)    // For each index 
  144.       this->data[i] = v.data[i];        // Copy value
  145.   }
  146.   return *this;                // Return CoolM_Vector reference
  147. }
  148.  
  149. // operator== -- Compare the elements of two Matrices of Type Type using
  150. //               the Compare pointer to funtion (default is ==). If one 
  151. //               CoolM_Vector has more elements than the other, the
  152. //               result is FALSE
  153. // Input:        Reference to CoolM_Vector of Type Type
  154. // Output:       TRUE/FALSE
  155.  
  156. template<class Type> 
  157. Boolean CoolM_Vector<Type>::operator== (const CoolM_Vector<Type>& v) const {
  158.   if (this->num_elmts != v.num_elmts)        // Size?
  159.     return FALSE;                // Then not equal
  160.   for (int i = 0; i < this->num_elmts; i++)    // For each index
  161.     if ((*this->compare_s)(this->data[i],v.data[i]) == FALSE) // Same?
  162.       return FALSE;                          // Then no match
  163.   return TRUE;                          // Else same, so return TRUE
  164. }
  165.  
  166. // is_data_equal -- Default data comparison function if user has not provided
  167. //                  another one. Note that this is not inline because we need
  168. //                  to take the address of it for the compare static variable
  169. // Input:           Two Type references
  170. // Output:          TRUE/FALSE
  171.  
  172. template<class Type>
  173. Boolean CoolM_Vector_is_data_equal (const Type& t1, const Type& t2) {
  174.   return (t1 == t2);
  175. }
  176.  
  177. // set_compare -- Specify the comparison function to be used
  178. //                in logical tests of vector elements
  179. // Input:         Pointer to a compare function
  180. // Output:        None
  181.  
  182. template<class Type> 
  183. void CoolM_Vector<Type>::set_compare (Boolean (*c) (const Type&, const Type&)) {
  184.   if (c == NULL)                // If no argument supplied
  185.     this->compare_s = &CoolM_Vector_is_data_equal; // Default is_equal
  186.   else
  187.     this->compare_s = c;            // Else set to user function
  188. }
  189.  
  190.  
  191. // operator<< -- Overload the output operator to print a vector
  192. // Input:        ostream reference, CoolM_Vector reference
  193. // Output:       ostream reference
  194.  
  195. template<class Type>
  196. ostream& operator<< (ostream& s, const CoolM_Vector<Type>& v) {
  197.    for (int i = 0; i < v.num_elmts; i++) {    // For each index in vector
  198.    s << v.data[i] << " ";            // Output data element
  199.    }
  200.    return (s);                    // Return ostream reference
  201. }
  202.  
  203. // operator+= -- Destructive vector addition of a scalar.
  204. // Input:        *this, scalar value
  205. // Output:       New vector reference
  206.  
  207. template<class Type> 
  208. CoolM_Vector<Type>& CoolM_Vector<Type>::operator+= (const Type& value) {
  209.   for (int i = 0; i < this->num_elmts; i++)    // For each index
  210.     this->data[i] += value;        // Add scalar
  211.   return *this;
  212. }
  213.  
  214. // operator*= -- Destructive vector multiplication by a scalar.
  215. // Input:        *this, scalar value
  216. // Output:       New vector reference
  217.  
  218.  
  219. template<class Type> 
  220. CoolM_Vector<Type>& CoolM_Vector<Type>::operator*= (const Type& value) {
  221.   for (int i = 0; i < this->num_elmts; i++)    // For each index
  222.     this->data[i] *= value;            // Multiply by scalar
  223.   return *this;
  224. }
  225.  
  226. // operator/= -- Destructive vector division by a scalar.
  227. // Input:        *this, scalar value
  228. // Output:       New vector reference
  229.  
  230. template<class Type> 
  231. CoolM_Vector<Type>& CoolM_Vector<Type>::operator/= (const Type& value) {
  232.   for (int i = 0; i < this->num_elmts; i++)    // For each index
  233.     this->data[i] /= value;            // division by scalar
  234.   return *this;
  235. }
  236.  
  237.  
  238. // operator+= -- Destructive vector addition with assignment. Note that the
  239. //               dimensions of each vector must be identical
  240. // Input:        *this, vector reference
  241. // Output:       Updated *this vector reference
  242.  
  243. template<class Type> 
  244. CoolM_Vector<Type>& CoolM_Vector<Type>::operator+= (const CoolM_Vector<Type>& v) {
  245.   if (this->num_elmts != v.num_elmts) // Size?
  246.     this->dimension_error ("operator+=", "Type", 
  247.                this->num_elmts, v.num_elmts);
  248.   for (int i = 0; i < this->num_elmts; i++)    // For each index
  249.     this->data[i] += v.data[i];            // Add elements
  250.   return *this;
  251. }
  252.  
  253.  
  254. // operator-= -- Destructive vector subtraction with assignment. Note that the
  255. //               dimensions of each vector must be identical
  256. // Input:        *this, vector reference
  257. // Output:       Updated *this vector reference
  258.  
  259. template<class Type> 
  260. CoolM_Vector<Type>& CoolM_Vector<Type>::operator-= (const CoolM_Vector<Type>& v) {
  261.   if (this->num_elmts != v.num_elmts)        // Size?
  262.     this->dimension_error ("operator-=", "Type", 
  263.                this->num_elmts, v.num_elmts);
  264.   for (int i = 0; i < this->num_elmts; i++)
  265.     this->data[i] -= v.data[i];
  266.   return *this;
  267. }
  268.  
  269.  
  270.  
  271. // pre_multiply -- Destructive pre_multiply vector with matrix. v = m * v
  272. //               num_cols of matrix must match num_elmts of vector
  273. // Input:        *this, matrix reference
  274. // Output:       Updated *this vector reference
  275.  
  276. template<class Type>
  277. CoolM_Vector<Type>& CoolM_Vector<Type>::pre_multiply (const CoolMatrix<Type>& m) {
  278.   if (m.columns() != this->num_elmts)        // dimensions do not match?
  279.     this->dimension_error ("operator*=", "Type", 
  280.                this->num_elmts, m.columns());
  281.   Type* temp= new Type[m.rows()];        // Temporary
  282.   CoolMatrix<Type>& mm = (CoolMatrix<Type>&) m;    // Drop const for get()
  283.   for (int i = 0; i < m.rows(); i++) {    // For each index
  284.     temp[i] = (Type) 0.0;            // Initialize element value
  285.     for (int k = 0; k < this->num_elmts; k++)    // Loop over column values
  286.       temp[i] += (mm.get(i,k) * this->data[k]); // Multiply
  287.   }
  288.   delete this->data;                // Free up the data space
  289.   num_elmts = m.rows();            // Set new num_elmts
  290.   this->data = temp;                // Pointer to new storage
  291.   return *this;                    // Return vector reference
  292. }
  293.  
  294. // post_multiply -- Destructive post_multiply vector with matrix. v = v * m
  295. //               num_elmts of vector must match num_rows of matrix 
  296. // Input:        *this, matrix reference
  297. // Output:       Updated *this vector reference
  298.  
  299. template<class Type> 
  300. CoolM_Vector<Type>& CoolM_Vector<Type>::post_multiply (const CoolMatrix<Type>& m) {
  301.   if (this->num_elmts != m.rows())        // dimensions do not match?
  302.     this->dimension_error ("operator*=", "Type", 
  303.                this->num_elmts, m.rows());
  304.   Type* temp= new Type[m.columns()];        // Temporary
  305.   CoolMatrix<Type>& mm = (CoolMatrix<Type>&) m;    // Drop const for get()
  306.   for (int i = 0; i < m.columns(); i++) {    // For each index
  307.     temp[i] = (Type) 0.0;            // Initialize element value
  308.     for (int k = 0; k < this->num_elmts; k++)    // Loop over column values
  309.       temp[i] += (this->data[k] * mm.get(k,i)); // Multiply
  310.   }
  311.   delete this->data;                // Free up the data space
  312.   num_elmts = m.columns();            // Set new num_elmts
  313.   this->data = temp;                // Pointer to new storage
  314.   return *this;                    // Return vector reference
  315. }
  316.  
  317.  
  318. // operator- -- Non-destructive vector negation. a = -b;
  319. // Input:       *this
  320. // Output:      New vector 
  321.  
  322. template<class Type> 
  323. CoolEnvelope< CoolM_Vector<Type> > CoolM_Vector<Type>::operator- () const {
  324.   CoolM_Vector<Type> temp(this->num_elmts);
  325.   for (int i = 0; i < this->num_elmts; i++)
  326.     temp.data[i] = - this->data[i];        // negate element
  327.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  328.   return result;                 // copy of envelope
  329. }
  330.  
  331. // operator+ -- Non-destructive vector addition of a scalar.
  332. // Input:       *this, scalar value
  333. // Output:      New vector 
  334.  
  335. template<class Type> 
  336. CoolEnvelope< CoolM_Vector<Type> > CoolM_Vector<Type>::operator+ (const Type& value) const {
  337.   CoolM_Vector<Type> temp(this->num_elmts);
  338.   for (int i = 0; i < this->num_elmts; i++)    // For each index
  339.     temp.data[i] = (this->data[i] + value);    // Add scalar
  340.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  341.   return result;                 // copy of envelope
  342. }
  343.  
  344.  
  345. // operator* -- Non-destructive vector multiply by a scalar.
  346. // Input:       *this, scalar value
  347. // Output:      New vector 
  348.  
  349. template<class Type> 
  350. CoolEnvelope< CoolM_Vector<Type> > CoolM_Vector<Type>::operator* (const Type& value) const {
  351.   CoolM_Vector<Type> temp(this->num_elmts);
  352.   for (int i = 0; i < this->num_elmts; i++)    // For each index
  353.     temp.data[i] = (this->data[i] * value);    // Multiply
  354.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  355.   return result;                 // copy of envelope
  356. }
  357.  
  358.  
  359. // operator/ -- Non-destructive vector division by a scalar.
  360. // Input:       *this, scalar value
  361. // Output:      New vector 
  362.  
  363. template<class Type> 
  364. CoolEnvelope< CoolM_Vector<Type> > CoolM_Vector<Type>::operator/ (const Type& value) const {
  365.   CoolM_Vector<Type> temp(this->num_elmts);
  366.   for (int i = 0; i < this->num_elmts; i++)    // For each index
  367.     temp.data[i] = (this->data[i] / value);    // Divide
  368.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  369.   return result;                 // copy of envelope
  370. }
  371.  
  372. // operator* -- Non-destructive multiply matrix with vector: vb = m * va
  373. //              num_cols of first matrix must match num_elmts of second vector.
  374. // Input:       matrix, vector reference
  375. // Output:      New vector 
  376.  
  377. template<class Type>
  378. CoolEnvelope< CoolM_Vector<Type> > operator* (const CoolMatrix<Type>& m, const CoolM_Vector<Type>& v) {
  379.   if (m.columns() != v.num_elmts)        // dimensions do not match?
  380.     v.dimension_error ("operator*", "Type", 
  381.                m.columns(), v.num_elmts);
  382.   CoolM_Vector<Type> temp(m.rows());        // Temporary
  383.   CoolMatrix<Type>& mm = (CoolMatrix<Type>&) m;    // Drop const for get()
  384.   for (int i = 0; i < m.rows(); i++) {    // For each index
  385.     temp.data[i] = (Type) 0.0;            // Initialize element value
  386.     for (int k = 0; k < v.num_elmts; k++)    // Loop over column values
  387.       temp.data[i] += (mm.get(i,k) * v.data[k]); // Multiply
  388.   }
  389.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  390.   return result;                 // copy of envelope
  391. }
  392.  
  393.  
  394. // operator* -- Non-destructive multiply vector with matrix: vb = va * m
  395. //              num_elmts of first vector must match num_rows of second matrix.
  396. // Input:       vector, matrix reference
  397. // Output:      New vector 
  398.  
  399. template<class Type>
  400. CoolEnvelope< CoolM_Vector<Type> > operator* (const CoolM_Vector<Type>& v, const CoolMatrix<Type>&m) {
  401.   if (v.num_elmts != m.rows())        // dimensions do not match?
  402.     v.dimension_error ("operator*", "Type", 
  403.                v.num_elmts, m.rows());
  404.   CoolM_Vector<Type> temp(m.columns());        // Temporary
  405.   CoolMatrix<Type>& mm = (CoolMatrix<Type>&) m;    // Drop const for get()
  406.   for (int i = 0; i < m.columns(); i++) {    // For each index
  407.     temp.data[i] = (Type) 0.0;            // Initialize element value
  408.     for (int k = 0; k < v.num_elmts; k++)    // Loop over column values
  409.       temp.data[i] += (v.data[k] * mm.get(k,i)); // Multiply
  410.   }
  411.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  412.   return result;                 // copy of envelope
  413. }
  414.  
  415.  
  416. // update -- replace a subvector of this, by the actual argument.
  417. // Input:       *this, starting corner specified by top and left.
  418. // Ouput:       mutated reference.
  419.  
  420. template<class Type> 
  421. CoolM_Vector<Type>& CoolM_Vector<Type>::update (const CoolM_Vector<Type>& v, 
  422.                       unsigned int start) {
  423.   unsigned int end = start + v.num_elmts;
  424.   if (this->num_elmts < end)
  425.     this->dimension_error ("update", "Type", 
  426.                end-start, v.num_elmts);
  427.   for (int i = start; i < end; i++)
  428.     this->data[i] = v.data[i-start];
  429.   return *this;
  430. }
  431.  
  432.  
  433. // extract -- Return a subvector specified by the start-left corner and size.
  434. // Input:       *this, starting corner specified by start and left, and size.
  435. // Ouput:       new vector
  436.  
  437. template<class Type> 
  438. CoolEnvelope< CoolM_Vector<Type> > CoolM_Vector<Type>::extract (unsigned int len, unsigned int start) const{
  439.   unsigned int end = start + len;
  440.   if (this->num_elmts < end)
  441.     this->dimension_error ("extract", "Type", 
  442.                end-start, len);
  443.   CoolM_Vector<Type> temp(len);
  444.   for (int i = 0; i < len; i++)
  445.     temp.data[i] = data[start+i];
  446.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  447.   return result;                 // copy of envelope
  448. }
  449.  
  450. // abs -- Return vector of absolute values.  v[i] = abs(v[i])
  451. // Input:       *this
  452. // Ouput:       new vector
  453.  
  454. template<class Type> 
  455. CoolEnvelope< CoolM_Vector<Type> > CoolM_Vector<Type>::abs() const {
  456.   CoolM_Vector<Type> temp(this->num_elmts);
  457.   for (int i = 0; i < this->num_elmts; i++)
  458.     if (this->data[i] < 0)
  459.       temp.data[i] = - this->data[i];
  460.     else
  461.       temp.data[i] = this->data[i];
  462.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  463.   return result;                 // copy of envelope
  464. }
  465.  
  466. // sign -- Mutate *this to store signs, either -1,1 or 0, depending on
  467. //         whether the corresponding values are negative, positive, or 0.
  468. // Input:       *this
  469. // Ouput:       *this mutated.
  470.  
  471. template<class Type> 
  472. CoolEnvelope< CoolM_Vector<Type> > CoolM_Vector<Type>::sign () const {
  473.   CoolM_Vector<Type> temp(this->num_elmts);
  474.   for (int i = 0; i < this->num_elmts; i++)
  475.     if (this->data[i] == 0)            // test fuzz equality to 0
  476.       temp.data[i] = 0;                // first.
  477.     else
  478.       if (this->data[i] < 0)
  479.     temp.data[i] = -1;
  480.       else
  481.     temp.data[i] = 1;
  482.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  483.   return result;                 // copy of envelope
  484. }
  485.  
  486. // element_product -- return the vector whose elements are the products 
  487. // Input:     2 vectors v1, v2 by reference
  488. // Output:    New vector, whose elements are v1[i]*v2[i].
  489.  
  490. template<class Type>
  491. CoolEnvelope< CoolM_Vector<Type> > element_product (const CoolM_Vector<Type>& v1, const CoolM_Vector<Type>& v2) {
  492.   if (v1.num_elmts != v2.num_elmts)        // Size?
  493.     v1.dimension_error ("element_product", "Type", 
  494.             v1.num_elmts, v2.num_elmts);
  495.   CoolM_Vector<Type> temp(v1.num_elmts);
  496.   for (int i = 0; i < v1.num_elmts; i++)
  497.     temp.data[i] = v1.data[i] * v2.data[i];
  498.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  499.   return result;                 // copy of envelope
  500. }
  501.  
  502. // element_quotient -- return the vector whose elements are the quotients 
  503. // Input:     2 vectors v1, v2 by reference
  504. // Output:    New vector, whose elements are v1[i]/v2[i].
  505.  
  506. template<class Type>
  507. CoolEnvelope< CoolM_Vector<Type> > element_quotient (const CoolM_Vector<Type>& v1, const CoolM_Vector<Type>& v2) {
  508.   if (v1.num_elmts != v2.num_elmts)        // Size?
  509.     v1.dimension_error ("element_quotient", "Type", 
  510.             v1.num_elmts, v2.num_elmts);
  511.   CoolM_Vector<Type> temp(v1.num_elmts);
  512.   for (int i = 0; i < v1.num_elmts; i++)
  513.     temp.data[i] = v1.data[i] / v2.data[i];
  514.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  515.   return result;                 // copy of envelope
  516. }
  517.  
  518.  
  519. // dot_product -- Return the dot product of the vectors
  520. // Input:       2 vectors by reference
  521. // Ouput:       dot product value
  522.  
  523. template<class Type>
  524. Type dot_product (const CoolM_Vector<Type>& v1, const CoolM_Vector<Type>& v2) {
  525.   if (v1.num_elmts != v2.num_elmts)        // Size?
  526.     v1.dimension_error ("dot_product", "Type", 
  527.             v1.num_elmts, v2.num_elmts);
  528.   Type dot = 0;
  529.   for (int i = 0; i < v1.num_elmts; i++)
  530.     dot += v1.data[i] * v2.data[i];    // of vectors
  531.   return dot;
  532. }
  533.  
  534. // cross_2d -- Return the 2X1 cross-product of 2 2d-vectors
  535. // Input:       2 vectors by reference
  536. // Ouput:       cross product value
  537.  
  538. template<class Type>
  539. Type cross_2d (const CoolM_Vector<Type>& v1, const CoolM_Vector<Type>& v2) {
  540.   if (v1.num_elmts != 2 || v2.num_elmts != 2)
  541.     v1.dimension_error ("cross_2d", "Type", 
  542.             v1.num_elmts, v2.num_elmts);
  543.  
  544.   return (v1.x() * v2.y()            
  545.       -                    
  546.       v1.y() * v2.x());
  547. }
  548.  
  549. // cross_3d -- Return the 3X1 cross-product of 2 3d-vectors
  550. // Input:       2 vectors by reference
  551. // Ouput:       3d cross product vector
  552.  
  553. template<class Type>
  554. CoolEnvelope< CoolM_Vector<Type> > cross_3d (const CoolM_Vector<Type>& v1, const CoolM_Vector<Type>& v2) {
  555.   if (v1.num_elmts != 3 || v2.num_elmts != 3)
  556.     v1.dimension_error ("cross_3d", "Type", 
  557.             v1.num_elmts, v2.num_elmts);
  558.   CoolM_Vector<Type> temp(v1.num_elmts);
  559.  
  560.   temp.x() = v1.y() * v2.z() - v1.z() * v2.y(); // work for both col/row
  561.   temp.y() = v1.z() * v2.x() - v1.x() * v2.z(); // representation
  562.   temp.z() = v1.x() * v2.y() - v1.y() * v2.x();
  563.   CoolEnvelope< CoolM_Vector<Type> >& result = (CoolEnvelope< CoolM_Vector<Type> >&) temp; // same physical object
  564.   return result;                 // copy of envelope
  565. }
  566.  
  567. //## hack to workaround BC++ 3.1 Envelope bug
  568. #undef CoolEnvelope
  569.  
  570.